﻿/*
 * Released under Microsoft Public License (Ms-PL) 
 * Sponsored by Development Platform Evangelism unit of Microsoft Israel
 * 
 * Copyright © 2008 by Tamir Khason
 * http://blogs.microsoft.co.il/blogs/tamir/
 * http://sharpsoft.net/
 * 
 * More information including licensing and term of use
 * can be found on http://www.codeplex.com/SilverlightRTL/
 * 
 */

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Globalization;

namespace System.Windows.BidiControls
{
    internal class TokenizerHelper
    {
        private char _argSeparator;
        private int _charIndex;
        internal int _currentTokenIndex;
        internal int _currentTokenLength;
        private bool _foundSeparator;
        private char _quoteChar;
        private string _str;
        private int _strLen;

        internal TokenizerHelper(string str)
        {
            char numericListSeparator = GetNumericListSeparator(CultureInfo.InvariantCulture);
            this.Initialize(str, '\'', numericListSeparator);
        }

        internal TokenizerHelper(string str, IFormatProvider formatProvider)
        {
            char numericListSeparator = GetNumericListSeparator(formatProvider);
            this.Initialize(str, '\'', numericListSeparator);
        }

        internal TokenizerHelper(string str, char quoteChar, char separator)
        {
            this.Initialize(str, quoteChar, separator);
        }

        internal string GetCurrentToken()
        {
            if (this._currentTokenIndex < 0)
            {
                return null;
            }
            return this._str.Substring(this._currentTokenIndex, this._currentTokenLength);
        }

        internal static char GetNumericListSeparator(IFormatProvider provider)
        {
            char ch = ',';
            NumberFormatInfo instance = NumberFormatInfo.GetInstance(provider);
            if ((instance.NumberDecimalSeparator.Length > 0) && (ch == instance.NumberDecimalSeparator[0]))
            {
                ch = ';';
            }
            return ch;
        }

        private void Initialize(string str, char quoteChar, char separator)
        {
            this._str = str;
            this._strLen = (str == null) ? 0 : str.Length;
            this._currentTokenIndex = -1;
            this._quoteChar = quoteChar;
            this._argSeparator = separator;
            while (this._charIndex < this._strLen)
            {
                if (!char.IsWhiteSpace(this._str, this._charIndex))
                {
                    return;
                }
                this._charIndex++;
            }
        }

        internal void LastTokenRequired()
        {
            if (this._charIndex != this._strLen)
            {
                Exceptions.ThrowInvalidOperationException("Last Token Required");
            }
        }

        internal bool NextToken()
        {
            return this.NextToken(false);
        }

        internal bool NextToken(bool allowQuotedToken)
        {
            return this.NextToken(allowQuotedToken, this._argSeparator);
        }

        internal bool NextToken(bool allowQuotedToken, char separator)
        {
            this._currentTokenIndex = -1;
            this._foundSeparator = false;
            if (this._charIndex >= this._strLen)
            {
                return false;
            }
            char c = this._str[this._charIndex];
            int i = 0;
            if (allowQuotedToken && (c == this._quoteChar))
            {
                i++;
                this._charIndex++;
            }
            int ci = this._charIndex;
            int idx = 0;
            while (this._charIndex < this._strLen)
            {
                c = this._str[this._charIndex];
                if (i > 0)
                {
                    if (c != this._quoteChar)
                    {
                        this._charIndex++;
                        idx++;
                        continue;
                    }
                    i--;
                    if (i != 0)
                    {
                        this._charIndex++;
                        idx++;
                        continue;
                    }
                    this._charIndex++;
                    break;
                }
                if (char.IsWhiteSpace(c) || (c == separator))
                {
                    if (c == separator)
                    {
                        this._foundSeparator = true;
                    }
                    break;
                }
                
            }
            if (i > 0)
            {
                Exceptions.ThrowInvalidOperationException("End Token is Missing");
            }
            this.ScanToNextToken(separator);
            this._currentTokenIndex = ci;
            this._currentTokenLength = idx;
            if (this._currentTokenLength < 1)
            {
                Exceptions.ThrowInvalidOperationException("Empty Token Found");
            }
            return true;
        }

        internal string NextTokenRequired()
        {
            if (!this.NextToken(false))
            {
                Exceptions.ThrowInvalidOperationException("Next Token Required");
            }
            return this.GetCurrentToken();
        }

        internal string NextTokenRequired(bool allowQuotedToken)
        {
            if (!this.NextToken(allowQuotedToken))
            {
                Exceptions.ThrowInvalidOperationException("Next Token Required");
            }
            return this.GetCurrentToken();
        }

        private void ScanToNextToken(char separator)
        {
            if (this._charIndex < this._strLen)
            {
                char c = this._str[this._charIndex];
                if ((c != separator) && !char.IsWhiteSpace(c))
                {
                    Exceptions.ThrowInvalidOperationException("No Separator Found");
                }
                int i = 0;
                while (this._charIndex < this._strLen)
                {
                    c = this._str[this._charIndex];
                    if (c == separator)
                    {
                        this._foundSeparator = true;
                        i++;
                        this._charIndex++;
                        if (i > 1)
                        {
                            Exceptions.ThrowInvalidOperationException("Empty Token Found");
                        }
                    }
                    else
                    {
                        if (!char.IsWhiteSpace(c))
                        {
                            break;
                        }
                        this._charIndex++;
                    }
                }
                if ((i > 0) && (this._charIndex >= this._strLen))
                {
                    Exceptions.ThrowInvalidOperationException("Emply Token Found");
                }
            }
        }

        internal bool FoundSeparator
        {
            get
            {
                return this._foundSeparator;
            }
        }
    }


}
